package com.sh.apiorder.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.sh.apicommon.common.ErrorCode;
import com.sh.apicommon.common.JwtUtils;
import com.sh.apicommon.entity.InterfaceInfo;
import com.sh.apicommon.entity.Order;
import com.sh.apicommon.entity.User;
import com.sh.apicommon.exception.BusinessException;
import com.sh.apicommon.service.ApiBackendService;
import com.sh.apicommon.vo.OrderVO;
import com.sh.apiorder.enums.OrderStatusEnum;
import com.sh.apiorder.mapper.TOrderMapper;
import com.sh.apiorder.model.dto.OrderAddRequest;
import com.sh.apiorder.model.dto.OrderQueryRequest;
import com.sh.apiorder.service.TOrderService;
import jakarta.annotation.Resource;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Queue;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessagePostProcessor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 舒云
* @description 针对表【t_order】的数据库操作Service实现
* @createDate 2024-10-06 16:12:03
*/
@Service
public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, Order>
    implements TOrderService {

    @Resource
    private Gson gson;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private ApiBackendService apiBackendService;

    @Resource
    private TOrderMapper orderMapper;
    @Resource
    private JmsTemplate jmsTemplate;

    @Autowired
    private MessageSenderService messageProducerService;

    public static final String USER_LOGIN_STATE = "user:login:";
    @Override
    public OrderVO addOrder(OrderAddRequest orderAddRequest, HttpServletRequest request) {
        //   1.订单服务校验参数，如用户是否存在，接口是否存在等校验
        if ( orderAddRequest==null){
            throw new  BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Long userId = orderAddRequest.getUserId();
        Long interfaceId = orderAddRequest.getInterfaceId();
        Double charging = orderAddRequest.getCharging();
        Integer count = orderAddRequest.getCount();
        BigDecimal totalAmount = orderAddRequest.getTotalAmount();
        if ( userId==null || interfaceId==null || count==null || totalAmount==null){
            throw new  BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if ( count<0 ){
            throw new  BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 获取登录用户
        User loginUser = this.getLoginUser(request);
        if ( loginUser==null){
            throw new  BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        InterfaceInfo interfaceInfo = apiBackendService.getInterfaceById(interfaceId);
        if ( interfaceInfo==null){
            throw new  BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 后台校验价格
        double temp = charging*count;
        BigDecimal bd = new BigDecimal(temp);
        double finalPrice = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        if (finalPrice != totalAmount.doubleValue()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "价格错误");
        }

        //        2.判断接口调用库存是否足够
        int interfaceStock = apiBackendService.getInterfaceStockById(interfaceId);
        if ( interfaceStock<=0 || interfaceStock<count){
            throw new  BusinessException(ErrorCode.PARAMS_ERROR,"库存不足");
        }
        //        3.扣减接口库存 远程调用实现
        boolean updateStockResult = apiBackendService.updateInterfaceStock(interfaceId, count);
        if ( !updateStockResult){
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"扣减库存失败");
        }
        //        4.数据库保存订单数据
        Order order = new Order();
        // 生成订单号
       String orderNum =  generateOrderNum(userId);
       order.setOrderSn(orderNum);
       order.setTotalAmount(totalAmount.doubleValue());
        BeanUtils.copyProperties(orderAddRequest,order);
        this.save(order); // 保存订单
        //        todo 5.同时消息队列发送延时消息
        messageProducerService.sendMessage(order, 60*30*1000L);
        //        6.构造订单详情并回显
        OrderVO orderVO = new OrderVO();
        generaOrderVO(orderVO, interfaceId, userId, orderNum, count, charging, totalAmount, order, interfaceInfo);
        return orderVO;
    }

    @Override
    public Page<OrderVO> listPageOrder(OrderQueryRequest orderQueryRequest, HttpServletRequest request) {
       Integer type = Integer.parseInt(orderQueryRequest.getType());
        long current = orderQueryRequest.getCurrent();
        long size = orderQueryRequest.getPageSize();
        if (  !OrderStatusEnum.getValues().contains(type)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);   // 订单状态错误
        }
        User loginUser = getLoginUser(request);
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", loginUser.getId()).eq("status", type);
        Page<Order> page = new Page<>(current, size);
        Page<Order> orderPage = this.page(page, queryWrapper);   // 所有数据
        Page<OrderVO> orderVOPage = new Page<>(orderPage.getCurrent(), orderPage.getPages(), orderPage.getRecords().size());  // 分页数据
        List<OrderVO> orderVOList = orderPage.getRecords().stream().map(order -> {
            Long interfaceId = order.getInterfaceId();
            InterfaceInfo interfaceInfo = apiBackendService.getInterfaceById(interfaceId);
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            orderVO.setTotal(Long.valueOf(order.getCount()));
            orderVO.setTotalAmount(order.getTotalAmount());
            orderVO.setOrderNumber(order.getOrderSn());
            orderVO.setInterfaceName(interfaceInfo.getName());
            orderVO.setInterfaceDesc(interfaceInfo.getDescription());
            orderVO.setExpirationTime(DateUtil.offset(order.getCreateTime(), DateField.MINUTE, 30));
            return orderVO;
        }).collect(Collectors.toList());
        orderVOPage.setRecords(orderVOList);
        return orderVOPage;

    }

    // region 工具方法

    /**
     * 生成订单详情
     * @param orderVO
     * @param interfaceId
     * @param userId
     * @param orderNum
     * @param count
     * @param charging
     * @param totalAmount
     * @param order
     * @param interfaceInfo
     */
    private static void generaOrderVO(OrderVO orderVO, Long interfaceId, Long userId, String orderNum, Integer count, Double charging, BigDecimal totalAmount, Order order, InterfaceInfo interfaceInfo) {
        orderVO.setInterfaceId(interfaceId);
        orderVO.setUserId(userId);
        orderVO.setOrderNumber(orderNum);
        orderVO.setTotal(Long.valueOf(count));
        orderVO.setCharging(charging);
        orderVO.setTotalAmount(totalAmount.doubleValue());
        orderVO.setStatus(order.getStatus());
        orderVO.setInterfaceDesc(interfaceInfo.getDescription());
        orderVO.setInterfaceName(interfaceInfo.getName());
        DateTime date = DateUtil.date();
        orderVO.setCreateTime(date);
        orderVO.setExpirationTime(DateUtil.offset(date, DateField.MINUTE, 30));
    }


    /**
     * 生成订单号
     * @param userId
     * @return
     */
    private String generateOrderNum(Long userId) {
        // 获取一个时间 ID，通常是通过某种分布式 ID 生成器生成的，可能包含时间戳等信息
        String timeId = IdWorker.getTimeId();
        // 从时间 ID 中截取一部分，去除最后 15 个字符
        String substring = timeId.substring(0, timeId.length() - 15);
        // 生成一个包含 5 位随机数字的字符串
        String randomNumbers = RandomUtil.randomNumbers(5);
        // 将截取的时间 ID 部分、随机数字和用户 ID 组合起来，作为订单号返回
        return substring + randomNumbers + userId;
    }


    /**
     * 获取登录用户
     * @param request
     * @return
     */
    public User getLoginUser(HttpServletRequest request) {
        // 先判断是否已登录
        Long userId = JwtUtils.getUserIdByToken(request);
        if (userId == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        String userJson = stringRedisTemplate.opsForValue().get(USER_LOGIN_STATE + userId);
        User user = gson.fromJson(userJson, User.class);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        return user;
    }


    @Override
    public List<Order> listTopBuyInterfaceInfo(int limit) {
        return orderMapper.listTopBuyInterfaceInfo(limit);
    }
    // endregion


}




